#include "autoresponder.h"

 AutoResponder *    AutoResponder::responder = NULL;

AutoResponder::AutoResponder( )
{}

AutoResponder * AutoResponder::Instance()
{
    if ( responder ==NULL)
    {
        responder = new AutoResponder;
        responder->create_test_data();
    }
    return responder;
}

void AutoResponder::create_test_data()
{
    test_node.clear();

    int cnt = qrand() % 10+2;
    QList <int> valid_id;
    memset(test_online, 0, 8 * sizeof(UINT));
    for ( int i =0; i < cnt; i ++)
    {
        int n = qrand() % 254 + 1;
        test_online[n/32] |= (1<<(n%32));

        valid_id.append(n);
    }


    for ( int i = 0; i < valid_id.count(); i++)
    {
        // if ( test_online[i/32] &(1<<i%32))
        {
            TOPO_NODE * node = new TOPO_NODE;
            node->_id = valid_id[i];

            TOPO_PHY * phy_1 = new TOPO_PHY( node->_id ,0 );
            phy_1->target = new TOPO_PHY( valid_id[ (i-1 + cnt)% cnt],  1);
            node->phy[0]= phy_1;

            TOPO_PHY * phy_2 = new TOPO_PHY(  node->_id, 1 );
            phy_2->target  = new TOPO_PHY(valid_id[(i+1 + cnt) % cnt], 0);
            node->phy[1] = phy_2;

            test_node[node-> _id] = node;
        }
    }

    test_count = test_node.count();

}

QByteArray AutoResponder::on_queryed(QextSerialPort* myCom,QByteArray query_str)
{
    bool ok;

    QByteArrayList list = query_str.split('\n' );

   QString ord = list[0].trimmed();
    QString info  =  list[1].trimmed() ;

   int ord_id = -1;
   QStringList varList ;
   if ( ord.contains(" "))
    {
         varList =   ord.split(" ");
       ord_id = varList[0].toInt(&ok, 16);
    }
   else
       ord_id =   ord.toInt(&ok, 16);

   QByteArray m_dataCom;


   static int mode = -1;
   static  int node_id = -1;
   static   int phy_id= -1;
   static  int rec_index =-1;

   switch (ord_id)
    {
   case 0:
   {
       m_dataCom = "0\r\n";
       bool reset = 0;
       bool shutdown = 0;
       bool cmder = 0;
       bool flash_err = 0;

       unsigned char dat =0;
       dat |= (reset << 31);
       dat |= (shutdown << 30);
       dat |= (cmder << 29);
       dat |= (flash_err << 28);


       test_count =  test_node.count();

       m_dataCom.append(QString("%1").arg(dat, 2, 16, QLatin1Char('0')));
       m_dataCom.append(QString("%1").arg(0, 2, 16, QLatin1Char('0')));
       m_dataCom.append(QString("%1").arg(test_count, 2, 16, QLatin1Char('0')));
       m_dataCom.append(QString("%1").arg(0, 2, 16, QLatin1Char('0')));
       m_dataCom .append("\r\n");

       myCom->write(m_dataCom);
   }
       break;

    case 5:

        mode = varList[1].midRef(0, 2).toInt(&ok, 16);
        node_id = varList[1].midRef(2, 2).toInt(&ok, 16);
        phy_id= varList[1].midRef(4, 2).toInt(&ok, 16);
        rec_index = varList[1].midRef(6, 2).toInt(&ok, 16);

        myCom->write(query_str);
        break;

    case 4:
    {
        TOPO_NODE * tmp_node ;
        if ( !test_node.contains(node_id))
        {   node_id =0;
            return "";
        }
        else
            tmp_node = test_node[node_id];
        switch(mode)
       {
       case 0:
            m_dataCom = "4\r\n";
           m_dataCom.append(QString("%1").arg(node_id, 2, 16, QLatin1Char('0')));
           m_dataCom.append(QString("%1").arg(0, 2, 16, QLatin1Char('0')));
           m_dataCom.append(QString("%1").arg(2, 2, 16, QLatin1Char('0')));
           m_dataCom.append(QString("%1").arg(2, 2, 16, QLatin1Char('0')));
           m_dataCom .append("\r\n");

           myCom->write(m_dataCom);
           break;

       case 1:
           m_dataCom =  "4\r\n" ;
           m_dataCom.append(QString("%1").arg(node_id,2, 16, QLatin1Char('0')));
           m_dataCom.append(QString("%1").arg(phy_id,2, 16, QLatin1Char('0')));
           m_dataCom.append(QString("%1").arg(2,2, 16, QLatin1Char('0')));  //???????
           m_dataCom.append(QString("%1").arg(2,2, 16, QLatin1Char('0')));  //???????
           m_dataCom.append("\r\n") ;

           myCom->write(m_dataCom);
           break;

       case 2:
           m_dataCom = "4\r\n";
           m_dataCom.append(QString("%1").arg(node_id, 2, 16, QLatin1Char('0')));
           m_dataCom.append(QString("%1").arg(phy_id, 2, 16, QLatin1Char('0')));

           if (tmp_node->phy.contains( phy_id) )
           {
               TOPO_PHY * phy_1 =  tmp_node->phy[phy_id];

               if( phy_1->target != NULL)
               {
                   m_dataCom.append(QString("%1").arg(phy_1->target->_node , 2, 16, QLatin1Char('0')));
                   m_dataCom.append(QString("%1").arg(phy_1->target->_phy, 2, 16, QLatin1Char('0')));
               }
           }


           m_dataCom.append("\r\n");

           myCom->write(m_dataCom);
           break;
       }
    }


        break;

    case 80:
    case 81:
    case 82:
    case 83:
    case 84:
    case 85:
    case 86:
    case 87:
       m_dataCom = query_str ;
       m_dataCom.append(QString("%1").arg(test_online[ord_id-80], 8, 16, QLatin1Char('0')));
       m_dataCom.append("\r\n");
          myCom->write(m_dataCom);
       break;
    }

    return m_dataCom;
}

void  AutoResponder::remove_node(int node_id)
{
    if ( AutoResponder::Instance()->test_node.contains(node_id))
    {
        TOPO_NODE * node = AutoResponder::Instance()->test_node[node_id];
        foreach ( TOPO_PHY * phy ,  node->phy)
        {
            int target_node_id = phy->target->_node;
            int target_phy_id = phy->target->_phy;

            if ( AutoResponder::Instance()->test_node.contains(target_node_id))
            {
                TOPO_NODE * target = AutoResponder::Instance()->test_node[target_node_id];
                target->phy[target_phy_id]->target = NULL;
            }
        }
        AutoResponder::Instance()->test_node.remove(node_id);
    }



    QList <int> valid_id =    AutoResponder::Instance()->test_node.keys();
     int cnt= AutoResponder::Instance()->test_node.count();
    memset(AutoResponder::Instance()->test_online, 0, 8 * sizeof(UINT));

    for ( int i =0; i < cnt; i ++)
    {
        int n = valid_id[i];
        AutoResponder::Instance()->test_online[n/32] |= (1<<(n%32));

    }
}

void    AutoResponder::remove_phy(int node_id, int phy_id)
{

    TOPO_NODE * node =  AutoResponder::Instance()->test_node[node_id];

    if (  node->phy.contains(phy_id) )
    {
        TOPO_PHY * phy =  node->phy[phy_id];
        node->phy.remove(phy_id);
        delete phy    ;

    }
    AutoResponder::Instance()->test_node[node_id] = node;

}

void  AutoResponder::remove_phy_target(int node_id, int phy_id)
{
    TOPO_NODE * node =  AutoResponder::Instance()->test_node[node_id];

    if (  node->phy.contains(phy_id) )
    {
        TOPO_PHY * phy =  node->phy[phy_id];
        if (phy->target !=NULL)
        {
            int target_node =  phy->target ->_node ;
            int target_phy =  phy->target ->_phy ;

            delete phy->target;

            phy->target = NULL  ;

            AutoResponder::Instance()->remove_phy_target( target_node,target_phy);

        }
    }
    AutoResponder::Instance()->test_node[node_id] = node;
}
